/*
 * Created on 2005-4-20
 *
 */
package com.xuln.common.base.dao;

import java.io.OutputStream;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.ehcache.Cache;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.LockMode;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import net.sf.hibernate.engine.SessionImplementor;
import net.sf.hibernate.impl.SessionImpl;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.hibernate.HibernateCallback;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;

import com.strongit.finance.common.support.DatabaseTableSupport;
import com.strongit.finance.common.support.FileUploadHelpBean;
import com.strongit.finance.common.support.GenerateIdentifierSupport;
import com.strongit.finance.common.support.NativeSqlSupport;
import com.strongit.finance.common.support.PreparedStatementSetter;
import com.strongit.finance.common.support.ResultSetCallBacker;
import com.strongit.finance.common.support.SplitPageHelpBean;
import com.strongit.finance.common.support.SplitPageQueryObjectSupport;
import com.strongit.finance.common.util.StoreProcedureCaller;
import com.strongit.finance.common.util.StringUtils;

/**
 * 这是Hibernate的数据库访问实现方式。 This class serves as the Base class for all other DAOs -
 * namely to hold common methods that they might all use. Can be used for
 * standard CRUD operations.
 * </p>
 * 
 * <p>
 * <a href="BaseDAOHibernate.java.html"> <i>View Source </i> </a>
 * </p>
 * 
 * @author <a href="mailto:wuyi@139sc.com">吴翊 </a>
 */
public class BaseDAO extends HibernateDaoSupport implements DAO {
	protected final Log log = LogFactory.getLog(getClass());

	/**
	 * cache对象实例，用于方法结果的缓存。
	 */
	private Cache cache;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getObjects(java.lang.Class)
	 */
	public List getObjects(Class clazz) {
		return getHibernateTemplate().loadAll(clazz);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getObject(java.lang.Class,
	 *      java.io.Serializable)
	 */
	public Object getObject(Class clazz, Serializable id) {
		Object o = getHibernateTemplate().get(clazz, id);
		return o;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#removeObject(java.lang.Class,
	 *      java.io.Serializable)
	 */
	public void removeObject(Class clazz, Serializable id) {
		getHibernateTemplate().delete(getObject(clazz, id));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#addObject(java.lang.Object)
	 */
	public void addObject(Object o) {
		getHibernateTemplate().save(o);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#updateObject(java.lang.Object)
	 */
	public void updateObject(Object o) {
		getHibernateTemplate().update(o);
	}

	/**
	 * Execute a named query for persistent instances, binding the properties of
	 * the given bean to ":" named parameters in the query string. A named query
	 * is defined in a Hibernate mapping file.
	 * 
	 * @param queryString -
	 *            the name of a Hibernate query in a mapping file
	 * @param bean -
	 *            the values of the parameters
	 * @return a List containing 0 or more persistent instances
	 * @deprecated replace with getObjects(final Class clazz, final
	 *             SplitPageHelpBean page)
	 */
	protected List getObjects(String queryString, Object bean) {
		return getHibernateTemplate().find(queryString, bean);
	}

	/**
	 * Execute a query for persistent instances, binding a number of values to
	 * "?" parameters in the query string.subclass must be this method.
	 * 
	 * @param queryString -
	 *            a query expressed in Hibernate's query language
	 * @param values -
	 *            the values of the parameters
	 * @return a List containing 0 or more persistent instances
	 * @deprecated replace with getObjects(final Class clazz, final
	 *             SplitPageHelpBean page)
	 */
	public List getObjects(String queryString, Object[] values) {
		return getHibernateTemplate().find(queryString, values);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getObjects(java.lang.Class,
	 *      com.strongit.finance.common.support.SplitPageHelpBean)
	 */
	public SplitPageHelpBean getObjects(final Class clazz,
			final SplitPageHelpBean page) {
		if (page == null) {
			SplitPageHelpBean page2 = new SplitPageHelpBean();
			List list = getObjects(clazz);
			page2.setTotalRecords(list.size());
			page2.setCurrentPage(1);
			page2.setRecordsPerPage(list.size());
			page2.setTotalPage(1);
			page2.setContent(list);
			return page2;
		}
		if (page.getCurrentPage() < 1) {
			page.setCurrentPage(1);
		}
		List list = getHibernateTemplate().executeFind(
				new SplitPageQueryObjectSupport(clazz, page, cache));
		page.setContent(list);
		return page;
	}

	/*
	 * 储存过程调用示例 processStoreProcedure("{ ? = call F_BASE_GETINNERCODE(?)}",new
	 * StoreProcedureCaller(){
	 * 
	 * public Object callStoreProcedure(CallableStatement stmt)throws
	 * SQLException { stmt.registerOutParameter(1,Types.VARCHAR);
	 * stmt.setString(2,"BUSER"); stmt.execute(); String result =
	 * stmt.getString(1); log.info("call store procedure result=" + result);
	 * return result; }
	 * 
	 * });
	 */
	/**
	 * 返回给定Class的名称的属性表示方式，如com.strongit.finance.common.dao.BaseDAO->baseDAO
	 * 
	 * @param clazz
	 *            需要获取名称的类型
	 * @return Class的名称的属性表示方式
	 */
	private String getFirstCharacterLowerCaseClassName(Class clazz) {
		String s = clazz.getName();
		if (s.indexOf('.') < 0) {
			return getFirstCharacterLowerCaseString(s);
		} else {
			return getFirstCharacterLowerCaseString(s.substring(s
					.lastIndexOf('.') + 1));
		}
	}

	/**
	 * 将给定字符串的首字母小写
	 * 
	 * @param name
	 *            需要首字母小写的字符串
	 * @return 首字母小写后的字符串
	 */
	private String getFirstCharacterLowerCaseString(String name) {
		String temp = name.substring(0, 1);
		return temp.toLowerCase() + name.substring(1);
	}

	/*
	 * @see com.strongit.finance.common.dao.DAO#getUniqueValue(java.lang.String)
	 */
	public Long getUniqueValue(final String uniqueName) {
		Object result = processStoreProcedure(
				"{ ? = call F_BASE_GETINNERCODE(?)}",
				new StoreProcedureCaller() {

					public Object callStoreProcedure(CallableStatement stmt)
							throws SQLException {
						stmt.registerOutParameter(1, Types.VARCHAR);
						stmt.setString(2, uniqueName);
						stmt.execute();
						String result = stmt.getString(1);
						log.info("call store procedure result=" + result);
						return result;
					}
				});
		if ("0".equals(result)) {
			throw new RuntimeException(uniqueName
					+ " column is not exists in table 'T_BASE_KEYNAME'");
		}
		return new Long((String) result);
	}

	/**
	 * 调用数据库的存储过程。
	 * 
	 * @param sql
	 *            调用数据库存储过程的sql语句。
	 * @param use
	 *            处理调用参数接口
	 * @return 调用存储过程的结果
	 */
	protected Object processStoreProcedure(final String sql,
			final StoreProcedureCaller use) {
		return getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				return NativeSqlSupport.processStoreProcedure(
						(SessionImpl) session, sql, use);
			}

		}, true);
	}

	/**
	 * 转换属性名称
	 * 
	 * @param sql
	 *            sql语句
	 * @param propertyNameList属性名称列表
	 * @param prefix
	 *            增加的前缀
	 * @return 转换后的字符串
	 */
	private String convertPropertyName(String sql, List propertyNameList,
			String prefix) {
		for (Iterator iter = propertyNameList.iterator(); iter.hasNext();) {
			String element = (String) iter.next();
			sql = StringUtils.replace(sql, "{" + element + "}", prefix
					+ element);
		}
		return sql;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getPropertyById(java.lang.Class,
	 *      java.lang.String, java.io.Serializable)
	 */
	public Object getPropertyValueByUniquePropertyValue(final Class clazz,
			final String propertyName, final String conditionPropertyName,
			final Serializable uniquePropertyValue) {
		return getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				StringBuffer buffer = new StringBuffer();
				String prefix = getFirstCharacterLowerCaseClassName(clazz);
				buffer.append("select ").append(prefix).append(".").append(
						propertyName).append(" from ").append(clazz.getName())
						.append(" as ").append(prefix).append(" where ")
						.append(prefix).append(".").append(
								conditionPropertyName).append("=?");
				String q = buffer.toString();
				Query query = session.createQuery(q);
				query.setParameter(0, uniquePropertyValue);
				return query.uniqueResult();
			}

		});
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getSomeProperties(java.lang.Class,
	 *      java.lang.String[],
	 *      com.strongit.finance.common.support.SplitPageHelpBean,boolean)
	 */
	public SplitPageHelpBean getSomeProperties(final Class clazz,
			final String[] properties, final SplitPageHelpBean page,
			boolean isDistinctByFirstProperty) {
		final StringBuffer outBuffer = new StringBuffer("select ");
		final String alias = getFirstCharacterLowerCaseClassName(clazz);
		if (properties == null || properties.length == 0) {
			outBuffer.append(alias).append('*');
		}

		for (int i = 0; i < properties.length; i++) {
			if (i == 0 && isDistinctByFirstProperty) {
				outBuffer.append("distinct ").append(alias).append(".").append(
						properties[i]);
			} else {
				outBuffer.append(alias).append(".").append(properties[i]);
			}
			if (i < properties.length - 1) {
				outBuffer.append(',');
			}
		}
		/*
		 * if(page == null){ SplitPageHelpBean page2 = new SplitPageHelpBean();
		 * page2.setContent(getObjects(clazz)); return page2; }
		 */
		if (page.getCurrentPage() < 1) {
			page.setCurrentPage(1);
		}
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				StringBuffer buffer = new StringBuffer();
				buffer.append(" from ").append(clazz.getName()).append(" as ")
						.append(alias);
				if (page.getQueryString() != null
						&& !"".equals(page.getQueryString().trim())) {
					if (page.getQueryString().trim().startsWith("order"))
						buffer.append(" where 1=1 ").append(
								page.getQueryString());
					else
						buffer.append(" where ").append(page.getQueryString());
				}
				String queryString = buffer.toString();
				queryString = convertPropertyName(queryString, StringUtils
						.getAllPropertyName(queryString), alias + ".");
				// 查询记录数
				Query query = session.createQuery("select count(*) "
						+ queryString);
				Object[] values = page.getValues();
				if (queryString.indexOf('?') > 0 && values != null) {
					for (int i = 0; i < values.length; i++) {
						query.setParameter(i, values[i]);
					}
				}
				int totalRecord = ((Integer) query.list().get(0)).intValue();
				page.setTotalRecords(totalRecord);
				int totalPage = 1;
				if (page.getRecordsPerPage() != -1) {
					totalPage = (totalRecord % page.getRecordsPerPage() == 0) ? totalRecord
							/ page.getRecordsPerPage()
							: totalRecord / page.getRecordsPerPage() + 1;
					page.setTotalPage(totalPage);
				} else
					page.setTotalPage(1);

				if (page.getCurrentPage() > totalPage)
					page.setCurrentPage(totalPage);

				// 查询结果
				queryString = outBuffer.append(queryString).toString();
				queryString = convertPropertyName(queryString, StringUtils
						.getAllPropertyName(queryString), alias + ".");
				query = session.createQuery(queryString);
				if (queryString.indexOf('?') > 0 && values != null) {
					for (int i = 0; i < values.length; i++) {
						query.setParameter(i, values[i]);
					}
				}
				if (page.getRecordsPerPage() != -1) {
					
					if(page.isUseFirstResultNum())
					{
						query.setFirstResult(page.getFirstResultNum());
					}
					else
					{
						query.setFirstResult((page.getCurrentPage() - 1)
							* page.getRecordsPerPage());
					}
					
					
					query.setMaxResults(page.getRecordsPerPage());
					
				}
				return query.list();
			}
		});
		page.setContent(list);
		return page;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#getObject(java.lang.Class,
	 *      java.io.Serializable, boolean)
	 */
	public Object getObject(Class clazz, Serializable id, boolean lock) {
		if (lock) {
			return getHibernateTemplate().load(clazz, id, LockMode.UPGRADE);
		} else
			return getObject(clazz, id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#lockObject(java.lang.Object)
	 */
	public void lockObject(Object object) {
		getHibernateTemplate().lock(object, LockMode.UPGRADE);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#evictObjectFromHibernateSession(java.lang.Object)
	 */
	public void evictObjectFromHibernateSession(Object object) {
		getHibernateTemplate().evict(object);
	}

	/*
	 * @see com.strongit.finance.common.dao.DAO#getSomeProperties(java.lang.Class,
	 *      java.lang.String[],
	 *      com.strongit.finance.common.support.SplitPageHelpBean)
	 */
	public SplitPageHelpBean getSomeProperties(Class clazz,
			String[] properties, SplitPageHelpBean page) {
		return getSomeProperties(clazz, properties, page, false);
	}

	/**
	 * process update without hibernate
	 * 
	 * @param sql -
	 *            sql statement
	 * @param ps -
	 *            preparedstatement that need set parameter
	 */
	protected void processUpdate(final String sql,
			final PreparedStatementSetter ps) {
		getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				NativeSqlSupport.processUpdate((SessionImpl) session, sql, ps);
				return null;
			}

		}, true);
	}

	/**
	 * process Update Without Batch
	 * 
	 * @param sql
	 *            sql语句
	 * @param ps
	 *            参数设置接口
	 */
	protected void processUpdateWithoutBatch(final String sql,
			final PreparedStatementSetter ps) {
		getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				NativeSqlSupport.processUpdateWithoutBatch(
						(SessionImpl) session, sql, ps);
				return null;
			}

		}, true);
	}

	/**
	 * process Query without hibernate
	 * 
	 * @param sql -
	 *            sql statement
	 * @param ps -
	 *            preparedstatement that need set parameter
	 * @param rs -
	 *            process ResultSet
	 * @return - an arbitrary result object, or null if none (the extractor will
	 *         typically be stateful in the latter case).
	 */
	protected Object processQuery(final String sql,
			final PreparedStatementSetter ps,
			final ResultSetCallBacker resultSetCallBacker) {
		return getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				return NativeSqlSupport.processQuery((SessionImpl) session,
						sql, ps, resultSetCallBacker);
			}

		}, true);
	}

	/**
	 * 获取当前Hibernate Session使用的数据库连接
	 * 
	 * @return 当前Hibernate Session使用的数据库连接
	 */
	public Connection getCurrentConnection() {
		try {
			Session session = getSession();
			if (session != null)
				return session.connection();
			else
				return null;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取给定表名称的主键最大值。
	 * 
	 * @param tableName
	 * @param addTableNameToKeyTableIfNeed
	 * @return 给定表名称的主键最大值
	 */
	protected Long getIdentifierValue(final String tableName,
			final boolean addTableNameToKeyTableIfNeed) {
		return GenerateIdentifierSupport.getIdentifierInNewTransaction(
				(SessionImplementor) getSession(), tableName,
				addTableNameToKeyTableIfNeed);
	}

	/*
	 * @see com.strongit.finance.common.dao.DAO#addOrUpdateObject(java.lang.Object)
	 */
	public void addOrUpdateObject(Object o) {
		getHibernateTemplate().saveOrUpdate(o);

	}

	/**
	 * 增加二进制文件到数据库中
	 * 
	 * @param file
	 *            需要增加的二进制文件对象
	 */
	protected void addFileUploadHelpBean(final FileUploadHelpBean file) {
		String sql = "insert into T_BASE_ATTACHMENT ("
				+ "ATTA_ID, ATTA_TYPE, ATTA_NAME, ATTA_SIZE, ATTA_UPLOADDATE, ATTA_CONTENT)"
				+ " values (?,?,?,?,?,empty_blob()) --write by wuyi";
		final long id = getIdentifierValue("T_BASE_ATTACHMENT", true)
				.longValue();
		file.setId(new Long(id));
		processUpdateWithoutBatch(sql, new PreparedStatementSetter() {

			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setLong(1, id);
				ps.setString(2, file.getContentType());
				ps.setString(3, file.getFileName());
				ps.setInt(4, file.getFileSize());
				ps
						.setDate(5, new java.sql.Date(file.getUploadDate()
								.getTime()));
			}
		});

		sql = "select ATTA_CONTENT from T_BASE_ATTACHMENT where ATTA_ID=? for update --write by wuyi";
		final Blob blob = (Blob) processQuery(sql,
				new PreparedStatementSetter() {

					public void setValues(PreparedStatement ps)
							throws SQLException {
						ps.setLong(1, id);

					}
				}, new ResultSetCallBacker() {

					public Object extractData(ResultSet rs) throws SQLException {
						Blob blob = null;
						if (rs.next()) {
							blob = rs.getBlob(1);
						}
						return blob;
					}
				});

		try {
			OutputStream out = (OutputStream) MethodUtils.invokeMethod(blob,
					"getBinaryOutputStream", null);//调用blob.getBinaryOutputStream方法
			out.write(file.getBytes());
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		sql = "update T_BASE_ATTACHMENT set ATTA_CONTENT=? where ATTA_ID=? ";
		processUpdateWithoutBatch(sql, new PreparedStatementSetter() {

			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setBlob(1, blob);
				ps.setLong(2, id);
			}

		});
	}

	/**
	 * 指定系统将使用的缓存。
	 * 
	 * @param cache
	 */
	public void setCache(Cache cache) {
		this.cache = cache;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.strongit.finance.common.dao.DAO#updateObjects(java.lang.Class,
	 *      java.util.Map, java.util.Map)
	 */
	public void updateObjects(Class clazz, Map propertyValue, Map param) {
		String tableName = DatabaseTableSupport.getTableName(clazz);
		final Set propertySet = propertyValue.entrySet();

		final Set paramSet = (param != null ? param.entrySet() : null);

		//构建sql语句
		StringBuffer buffer = new StringBuffer();
		buffer.append("update ").append(tableName).append(" ");
		buffer.append("set ");
		int i = 0;
		for (Iterator iter = propertySet.iterator(); iter.hasNext(); i++) {
			Map.Entry element = (Map.Entry) iter.next();
			buffer.append(DatabaseTableSupport.getColumnNameByPropertyName(
					clazz, (String) element.getKey()));
			buffer.append("=?");
			if (i < propertySet.size() - 1) {
				buffer.append(',');
			}
		}
		if (paramSet != null) {
			i = 0;
			buffer.append(" where ");
			for (Iterator iter = paramSet.iterator(); iter.hasNext(); i++) {
				Map.Entry element = (Map.Entry) iter.next();
				buffer.append(DatabaseTableSupport.getColumnNameByPropertyName(
						clazz, (String) element.getKey()));
				buffer.append("=?");
				if (i < paramSet.size() - 1) {
					buffer.append(" and ");
				}
			}
		}

		//更新数据库
		processUpdate(buffer.toString(), new PreparedStatementSetter() {

			public void setValues(PreparedStatement ps) throws SQLException {
				int i = 1;
				for (Iterator iter = propertySet.iterator(); iter.hasNext(); i++) {
					Map.Entry element = (Map.Entry) iter.next();
					if (element.getValue() != null) {
						ps.setObject(i, element.getValue());
					} else {
						ps.setNull(i, Types.VARCHAR);
					}
				}
				if (paramSet != null) {
					for (Iterator iter = paramSet.iterator(); iter.hasNext(); i++) {
						Map.Entry element = (Map.Entry) iter.next();
						if (element.getValue() != null) {
							ps.setObject(i, element.getValue());
						} else {
							ps.setNull(i, Types.VARCHAR);
						}
					}
				}
			}
		});
	}

	/** 以下方法由xuzm 添加，主要是处理批量操作数据库的问题** */
	/**
	 * 批量操作保存和添加
	 */
	public void saveOrUpdateObjects(List objects) {
		getHibernateTemplate().saveOrUpdateAll(objects);
	}

	/**
	 * 批量添加
	 * 
	 * @param objects
	 */
	public void addObjects(List objects) {
		getHibernateTemplate().saveOrUpdateAll(objects);
	}

	/**
	 * 批量更新
	 * 
	 * @param objects
	 */
	public void updateObjects(List objects) {
		getHibernateTemplate().saveOrUpdateAll(objects);
	}

	/**
	 * 批量删除
	 * 
	 * @param objects
	 */
	public void removeObjects(List objects) {
		getHibernateTemplate().deleteAll(objects);
	}

	/**
	 * 批量添加
	 */

	//	public void addObjects(List objects, Class clazz) throws Exception {
	//		String tableName = this.getTableName(clazz);
	//		String identifierName = getIdentifierName(clazz);
	//		String identifierProp = DatabaseTableSupport
	//				.getIdentifierPropertyName(clazz);
	//		Statement ps = null;
	//		Map columnValues = null;
	//		List columnNames = DatabaseTableSupport.getAllColumnName(clazz);
	//		List columnTypes = new ArrayList();
	//		try {
	//			Connection conn = getCurrentConnection();
	//			Object id = new Object();
	//			ps = conn.createStatement();
	//			for (int i = 0; i < columnNames.size(); i++) {
	//				columnTypes.add(((String[]) columnNames.get(i))[2]);
	//			}
	//			for (int i = 0; i < objects.size(); i++) {
	//				Object object = objects.get(i);
	//				id = MethodUtils.invokeMethod(object,
	//						toGetMethod(identifierProp), null);
	//				columnValues = getColumnValue(object, clazz, columnNames);
	//				String addSql = generateAddObjectSql(id, identifierName,
	//						tableName, columnValues, columnTypes);
	//				log.info(addSql);
	//				ps.addBatch(addSql);
	//
	//			}
	//			ps.executeBatch();
	//		} catch (Exception ex) {
	//			log.error("error for addObjects", ex);
	//			throw ex;
	//		} finally {
	//			if (ps != null) {
	//				ps.close();
	//				ps = null;
	//			}
	//
	//		}
	//	}
	/**
	 * 批量更新
	 */
	public void updateObjects(List objects, Class clazz) throws Exception {
		String tableName = this.getTableName(clazz);
		String identifierName = getIdentifierName(clazz);
		String identifierProp = DatabaseTableSupport
				.getIdentifierPropertyName(clazz);
		Statement ps = null;
		Map columnValues = null;
		List columnNames = DatabaseTableSupport.getAllColumnName(clazz);
		List columnTypes = new ArrayList();
		try {
			Connection conn = getCurrentConnection();
			Object id = new Object();
			ps = conn.createStatement();
			for (int i = 0; i < columnNames.size(); i++) {
				columnTypes.add(((String[]) columnNames.get(i))[2]);
			}
			for (int i = 0; i < objects.size(); i++) {
				Object object = objects.get(i);
				id = MethodUtils.invokeMethod(object,
						toGetMethod(identifierProp), null);
				columnValues = getColumnValue(object, clazz, columnNames);
				String updateSql = generateUpdateObjectSql(id, identifierName,
						tableName, columnValues, columnTypes);
				log.info(updateSql);
				ps.addBatch(updateSql);

			}
			ps.executeBatch();
		} catch (Exception ex) {
			log.error("error for updateObjects", ex);
			throw ex;
		} finally {
			if (ps != null) {
				ps.close();
				ps = null;
			}

		}
	}

	/**
	 * 批量更新部分列
	 */
	public void updateObjects(List propertyValueList, List paramList,
			Class clazz) throws Exception {
		String tableName = this.getTableName(clazz);
		Statement ps = null;
		Map propertyColumnMap = new HashMap();
		Map propertyValueMap = null;
		Map paramMap = null;
		try {
			Connection conn = getCurrentConnection();
			ps = conn.createStatement();
			propertyColumnMap = DatabaseTableSupport
					.getAllPropertyColumn(clazz);//获取属性对应的表列名
			String identifierName = DatabaseTableSupport
					.getIdentifierPropertyName(clazz);
			for (int i = 0; i < propertyValueList.size(); i++) {
				propertyValueMap = (Map) propertyValueList.get(i);
				paramMap = (Map) paramList.get(i);
				String filterSql = this.generateUpdateObjectFilterSql(paramMap,
						propertyColumnMap, clazz);
				String updateSql = generateUpdateObjectSql(tableName,
						propertyValueMap, propertyColumnMap, filterSql,
						identifierName, clazz);
				log.info(updateSql);
				ps.addBatch(updateSql);

			}
			ps.executeBatch();
		} catch (Exception ex) {
			log.error("error for updateObjects", ex);
			throw ex;
		} finally {
			if (ps != null) {
				ps.close();
				ps = null;
			}
			propertyColumnMap = null;
			propertyValueMap = null;
			paramMap = null;

		}
	}

	/**
	 * 批量更新部分列
	 * 
	 * @param propertyValueList
	 * @param identifierName
	 * @param clazz
	 * @throws Exception
	 */
	public void updateObjects(List propertyValueList, Class clazz,
			String identifierName) throws Exception {
		String tableName = this.getTableName(clazz);
		Statement ps = null;
		Map propertyColumnMap = new HashMap();
		Map propertyValueMap = null;
		try {
			Connection conn = getCurrentConnection();
			ps = conn.createStatement();
			if (identifierName == null || identifierName.equals("")) {
				identifierName = DatabaseTableSupport
						.getIdentifierPropertyName(clazz);
			}
			String identifierColumnName = DatabaseTableSupport
					.getColumnNameByPropertyName(clazz, identifierName);
			//	log.info("this identifierName is " + identifierName);

			StringBuffer filterSql = new StringBuffer();
			//filterSql.append(identifierName).append("=");

			propertyColumnMap = DatabaseTableSupport
					.getAllPropertyColumn(clazz);//获取属性对应的表列名

			for (int i = 0; i < propertyValueList.size(); i++) {
				propertyValueMap = (Map) propertyValueList.get(i);
				filterSql.setLength(0);
				filterSql.append(" where ");
				filterSql.append(identifierColumnName).append("=");
				Object identifierValue = propertyValueMap.get(identifierName);
				if (identifierValue == null) {
					filterSql.append("1=0");
				} else if (identifierValue instanceof String) {
					filterSql.append("'").append(identifierValue).append("'");
				} else {
					filterSql.append("'").append(identifierValue).append("'");
				}
				String updateSql = generateUpdateObjectSql(tableName,
						propertyValueMap, propertyColumnMap, filterSql
								.toString(), identifierName, clazz);
				log.info(updateSql);
				ps.addBatch(updateSql);

			}
			ps.executeBatch();
		} catch (Exception ex) {
			log.error("error for updateObjects", ex);
			throw ex;
		} finally {
			if (ps != null) {
				ps.close();
				ps = null;
			}
			propertyColumnMap = null;
			propertyValueMap = null;
		}
	}

	/**
	 * 批量删除
	 */

	public void removeObjects(Object[] ids, Class clazz) throws Exception {

		String tableName = this.getTableName(clazz);
		String identifierName = getIdentifierName(clazz);
		Statement ps = null;
		Connection conn = getCurrentConnection();
		try {
			ps = conn.createStatement();
			for (int i = 0; i < ids.length; i++) {
				String removeSql = generateRemoveObjectSql(ids[i],
						identifierName, tableName);
				log.info(removeSql);
				ps.addBatch(removeSql);

			}
			ps.executeBatch();
		} catch (Exception ex) {
			log.error("error for removeObjects", ex);
			throw ex;
		} finally {
			if (ps != null) {
				ps.close();
				ps = null;
			}

		}
	}

	private String getTableName(Class clazz) {
		return DatabaseTableSupport.getTableName(clazz);
	}

	private String getIdentifierName(Class clazz) {
		return DatabaseTableSupport.getUniqueColumnNameByPropertyName(clazz,
				null, true);
	}

	private String generateRemoveObjectSql(Object id, String identifierName,
			String tableName) {
		StringBuffer removeSql = new StringBuffer();

		removeSql.append("delete from ").append(tableName).append(" where ")
				.append(identifierName).append("=");
		if (id instanceof String) {
			removeSql.append("'").append(id).append("'");
		} else if (id instanceof Long) {
			removeSql.append(id);
		}

		return removeSql.toString();

	}

	/**
	 * 产生更新的ＳＱＬ语句
	 * 
	 * @param id
	 * @param identifierName
	 * @param tableName
	 * @param cloumn
	 * @param columnType
	 * @return
	 */
	private String generateUpdateObjectSql(Object id, String identifierName,
			String tableName, Map cloumn, List columnType) {
		StringBuffer updateSql = new StringBuffer();
		updateSql.append("update ").append(tableName).append(" set ");
		Iterator iter = cloumn.entrySet().iterator();
		// Object removeKey = null;
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			Object key = entry.getKey();
			Object val = entry.getValue();

			if (val != null) {
				if (val instanceof String) {
					updateSql.append(String.valueOf(key)).append("='").append(
							val).append("'");
				} else {
					updateSql.append(String.valueOf(key)).append("=").append(
							val).append("");
				}

				updateSql.append(",");
			}
		}
		if (updateSql.indexOf(",") > 0) {
			updateSql.deleteCharAt(updateSql.lastIndexOf(","));
		} else {
			updateSql.append("1=1");
		}
		updateSql.append(" where ").append(identifierName).append("=");

		if (id instanceof String) {
			updateSql.append("'").append(id).append("'");
		} else if (id instanceof Long) {
			updateSql.append(id);
		}

		return updateSql.toString();
	}

	/**
	 * 产生更新SQL
	 * 
	 * @param tableName
	 * @param propertyMap
	 * @param filterSql
	 * @param clazz
	 * @return
	 */
	private String generateUpdateObjectSql(String tableName, Map propertyMap,
			Map propertyColumnMap, String filterSql,
			String identifierPropertyName, Class clazz) {
		StringBuffer updateSql = new StringBuffer();
		updateSql.append("update ").append(tableName).append(" set ");
		Iterator iter = propertyMap.entrySet().iterator();
		//		String identifierPropertyName = DatabaseTableSupport
		//				.getIdentifierPropertyName(clazz);
		//	log.info("this identifierPropertyName is " + identifierPropertyName);
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			Object key = entry.getKey();
			Object val = entry.getValue();
			if (key.equals(identifierPropertyName)) {
				continue;
			}
			key = propertyColumnMap.get((String) key);
			if (val != null) {
				if (val instanceof String) {
					updateSql.append(String.valueOf(key)).append("='").append(
							val).append("'");
				} else {
					updateSql.append(String.valueOf(key)).append("=").append(
							val).append("");
				}

				updateSql.append(",");
			}
		}
		if (updateSql.indexOf(",") > 0) {
			updateSql.deleteCharAt(updateSql.lastIndexOf(","));
		} else {
			updateSql.append("1=1");
		}
		updateSql.append(filterSql);

		return updateSql.toString();
	}

	/**
	 * 产生更新的过滤条件的SQL
	 * 
	 * @param paramMap
	 * @param clazz
	 * @return
	 */
	private String generateUpdateObjectFilterSql(Map paramMap,
			Map propertyColumnMap, Class clazz) {
		StringBuffer updateSql = new StringBuffer();
		updateSql.append(" where ");
		final Set paramSet = paramMap.entrySet();

		// Object removeKey = null;
		boolean haseNext = false;
		int i = 0;
		for (Iterator iter2 = paramSet.iterator(); iter2.hasNext(); i++) {
			haseNext = true;
			Map.Entry entry = (Map.Entry) iter2.next();
			Object key = entry.getKey();
			Object val = entry.getValue();
			key = propertyColumnMap.get((String) key);
			if (val != null) {
				if (val instanceof String) {
					updateSql.append(String.valueOf(key)).append("='").append(
							val).append("'");
				} else {
					updateSql.append(String.valueOf(key)).append("=").append(
							val).append("");
				}
				if (i < paramSet.size() - 1) {
					updateSql.append(" and ");
				}

			}
		}

		return updateSql.toString();
	}

	/**
	 * 产生添加的SQL语句
	 * 
	 * @param id
	 * @param identifierName
	 * @param tableName
	 * @param cloumn
	 * @param columnType
	 * @return
	 */
	private String generateAddObjectSql(Object id, String identifierName,
			String tableName, Map cloumn, List columnType) {
		StringBuffer addSql = new StringBuffer();
		addSql.append("insert into  ").append(tableName).append("(");
		Iterator iter = cloumn.entrySet().iterator();
		StringBuffer cloumnSql = new StringBuffer();
		StringBuffer valueSql = new StringBuffer();
		// Object removeKey = null;
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			Object key = entry.getKey();
			Object val = entry.getValue();

			if (val != null) {
				cloumnSql.append(String.valueOf(key));
				if (val instanceof String) {
					valueSql.append("'").append(val).append("'");
				} else {
					valueSql.append(val);
				}
				valueSql.append(",");
				cloumnSql.append(",");
			}
		}
		if (valueSql.indexOf(",") > 0) {
			valueSql.deleteCharAt(valueSql.lastIndexOf(","));
		}
		if (cloumnSql.indexOf(",") > 0) {
			cloumnSql.deleteCharAt(cloumnSql.lastIndexOf(","));
		}
		addSql.append(cloumnSql).append(")").append(" values(")
				.append(valueSql).append(")");

		return addSql.toString();
	}

	/**
	 * 获取列值
	 * 
	 * @param object
	 * @param clazz
	 * @param columnNames
	 * @return
	 */
	private Map getColumnValue(Object object, Class clazz, List columnNames) {
		Map columnValues = new HashMap();

		log.info("this column names size is " + columnNames.size());
		try {
			for (int i = 0; i < columnNames.size(); i++) {
				String cloumnName[] = (String[]) columnNames.get(i);
				Object columnValue = null;

				if (cloumnName[2].indexOf(".") > 0) {//如果列的类型为实体类时,如salaryType.id
					// 时
					Object subObject = MethodUtils.invokeMethod(object,
							toGetMethod(cloumnName[0]), null);
					columnValue = MethodUtils.invokeMethod(subObject,
							toGetMethod(DatabaseTableSupport
									.getIdentifierPropertyName(Class
											.forName(cloumnName[2]))), null);
					//					log
					//							.info("this bean property value is (.) "
					//									+ columnValue);
				} else {
					columnValue = MethodUtils.invokeMethod(object,
							toGetMethod(cloumnName[0]), null);
				}

				columnValues.put(cloumnName[1], columnValue);
			}
		} catch (Exception ex) {
			log.error("error for getColumnValue", ex);
		}

		return columnValues;

	}

	private static String toGetMethod(String propName) {
		String a = propName.substring(0, 1).toUpperCase();
		String b = propName.substring(1, propName.length());
		return "get" + a + b;
	}

}